<?php

namespace App\Service;

use App\Constants\QmGame;
use App\Model\QmGameList;
use GuzzleHttp\Exception\GuzzleException;
use Hyperf\Guzzle\ClientFactory;
use Hyperf\Di\Annotation\Inject;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class TiktokPayService {
    /**
     * @Inject
     * @var ClientFactory
     */
    protected ClientFactory $clientFactory;

    private array $config = [
        'offerId' => '1450036659'
    ];

    public function getOfferId() {
        return $this->config['offerId'];
    }

    /**
     * 请求抖音支付接口
     * @param $orderInfo
     * @return mixed
     * @throws ContainerExceptionInterface
     * @throws GuzzleException
     * @throws NotFoundExceptionInterface
     */
    public function doPay($orderInfo): mixed {
        $client = $this->clientFactory->create(['verify' => false]);
        $gameInfo = QmGameService::getGameInfo($orderInfo['game_hash']);
        $accessToken = $this->getAccessToken($gameInfo);

        $uri = '/api/apps/game/wallet/game_pay';
        $url = "https://developer.toutiao.com{$uri}";
        $postData = [
            'access_token' => $accessToken,
            'openid'       => $orderInfo['openid'],
            'appid'        => $gameInfo['app_id'],
            'ts'           => time(),
            'zone_id'      => '1',
            'pf'           => 'android',
            'amt'          => $orderInfo['money'],
            'bill_no'      => $orderInfo['order_num']
        ];
        $signStr = $this->getSignStr($postData, $uri);

        $response = $client->post($url, [
            'json' => [
                ...$postData,
                'mp_sig' => $signStr
            ]
        ]);
        return json_decode($response->getBody()->getContents(), true);
    }

    /**
     * 查询抖音余额
     * @param $orderInfo
     * @return mixed
     * @throws GuzzleException
     */
    public function getBalance($orderInfo): mixed {
        $client = $this->clientFactory->create(['verify' => false]);
        $gameInfo = QmGameService::getGameInfo($orderInfo['game_hash']);
        $accessToken = $this->getAccessToken($gameInfo);

        $uri = '/api/apps/game/wallet/get_balance';
        $url = "https://developer.toutiao.com{$uri}";
        $postData = [
            'access_token' => $accessToken,
            'openid'       => $orderInfo['openid'],
            'appid'        => $gameInfo['app_id'],
            'ts'           => time(),
            'zone_id'      => '1',
            'pf'           => 'android'
        ];
        $signStr = $this->getSignStr($postData, $uri);

        $response = $client->post($url, [
            'json' => [
                ...$postData,
                'mp_sig' => $signStr
            ]
        ]);

        return json_decode($response->getBody()->getContents(), true);
    }

    /**
     * 订单检查
     * @param $orderInfo
     * @return mixed
     * @throws GuzzleException
     */
    public function checkOrder($orderInfo): mixed {
        $client = $this->clientFactory->create(['verify' => false]);
        $gameInfo = QmGameService::getGameInfo($orderInfo['game_hash']);
        $accessToken = $this->getAccessToken($gameInfo);

        $url = "https://developer.toutiao.com/api/apps/game/payment/queryPayState";
        $response = $client->get($url, [
            'query' => [
                'access_token' => $accessToken,
                'orderno'      => $orderInfo['order_num']
            ]
        ]);

        return json_decode($response->getBody()->getContents(), true);
    }

    /**
     * 获取小程序AccessToken
     * @param $gameInfo
     * @return mixed
     * @throws GuzzleException
     */
    public function getAccessToken($gameInfo): mixed {
        $client = $this->clientFactory->create(['verify' => false]);
        $atPath = QmGame::MINI_APP_ACCESS_TOKEN . $gameInfo['app_id'];
        if (file_exists($atPath)) {
            $accessTokenConf = file_get_contents($atPath);
            $accessTokenArr = json_decode($accessTokenConf, true);
            if ($accessTokenArr['end'] >= time()) {
                return $accessTokenArr['value'];
            }
        }

        $response = $client->post(
            'https://developer.toutiao.com/api/apps/v2/token',
            [
                'json' => [
                    'appid'      => $gameInfo['app_id'],
                    'secret'     => $gameInfo['app_secret'],
                    'grant_type' => 'client_credential'
                ]
            ]
        );
        $content = json_decode($response->getBody()->getContents(), true);
        if (!empty($content['data']['access_token'])) {
            $accessTokenArr = [
                'end'   => time() + 6000,
                'value' => $content['data']['access_token']
            ];
            file_put_contents($atPath, json_encode($accessTokenArr));

            return $content['data']['access_token'];
        } else {
            return '';
        }
    }

    /**
     * 敏感词检测
     * @param $gameInfo
     * @param $userInfo
     * @param $msg
     * @return bool
     * @throws GuzzleException
     */
    public function checkMsg($gameInfo, $userInfo, $msg): bool {
        $client = $this->clientFactory->create(['verify' => false]);
        $accessToken = $this->getAccessToken($gameInfo);

        $url = "https://developer.toutiao.com/api/v2/tags/text/antidirt";
        $response = $client->post($url, [
            'json'    => [
                'tasks' => [
                    'content' => $msg
                ]
            ],
            'headers' => [
                'X-Token' => $accessToken
            ]
        ]);
        $content = json_decode($response->getBody()->getContents(), true);
        if (!isset($content['error_id'])) {
            return !$content['data'][0]['predicts']['hit'];
        } else {
            return true;
        }
    }

    /**
     * 计算支付秘钥
     * @param $data
     * @param $uri
     * @return false|string
     */
    private function getSignStr($data, $uri): bool|string {
        $key = 'd88d14af20ae7828e6bbbc7dc38e4169';
        ksort($data);

        $str = http_build_query($data) . "&org_loc={$uri}&method=POST";

        return hash_hmac('sha256', $str, $key);
    }
}